import os
import sys  # 导入sys模块
import random
sys.setrecursionlimit(3000)  # 将默认的递归深度修改为3000


class MazeData(object):
    def __init__(self, row, col):
        self.row = row
        self.col = col
        self.entrance = [1, 0]
        self.exit = [row - 2, col - 1]
        self.direction = ((-1, 0), (0, 1), (1, 0), (0, -1))
        filename = f'maze_{row}_{col}.txt'
        filenameList = os.listdir('/')
        if filename in filenameList:
            with open(filename) as fp:
                data = fp.readlines()[1:]
                self.data = [[i for i in j[:-1]] for j in data]
        else:
            # TODO:
            self.generate_data()
            self.data[self.entrance[0]][self.entrance[1]]=self.data[self.exit[0]][self.exit[1]] = ' '
            self.save()
        self.visited = [[False for _ in range(col)] for _ in range(row)]

    def save(self,filename=''):
        if not filename:
            filename = f'maze_{self.row}_{self.col}.txt'
        with open(filename,'w') as fp:
            fp.write(f'{self.row} {self.col}\r')
            for row in self.data:
                for col in row:
                    fp.write(col)
                fp.write('\r')

    def merge(self):
        mergeData = [[col for col in row] for row in self.data]
        self.generate_data()
        for row in range(self.row):
            for col in range(self.col):
                self.data[row][col] = '#' if self.data[row][col]==mergeData[row][col]=='#' else ' '
        self.visited = [[False for _ in range(self.col)] for _ in range(self.row)]
        # self.save(f'merge_{self.row}_{self.col}.txt')
        self.save()


    def generate_data(self):
        if self.row % 2 == 0 or self.col % 2 == 0:
            print("行列值都必须为奇数！")
            exit()
        self.data = [
            [' ' if i % 2 == 1 else '#' for i in range(self.col)] if j % 2 == 1 else ['#' for _ in range(self.col)]
            for j in range(self.row)]
        self.visited = [[False for _ in range(self.col)] for _ in range(self.row)]
        self.generator(1,1)
        self.visited = [[False for _ in range(self.col)] for _ in range(self.row)]
    def generator(self,row,col):
        # TODO:
        for i in range(4):
            newRow = row + self.direction[i][0]*2
            newCol = col + self.direction[i][1]*2
            if self.isInArea(newRow,newCol) and (not self.visited[newRow][newCol]):
                self.visited[newRow][newCol] = True
                self.data[row + self.direction[i][0]][col + self.direction[i][1]] = ' '
                self.generator(newRow,newCol)
    def isInArea(self, row, col):
        # TODU:下式可简化
        return row >= 0 and row < self.row and col >= 0 and col < self.col

class MazeData2(MazeData):
    def generator(self,row,col):
        stack = [[row, col]]
        while stack:
            num = random.randint(0,len(stack)-1)
            row, col = stack.pop(num)
            for dCol, dRow in self.direction:
                if self.isInArea(row + 2*dRow, col + 2*dCol) and (
                        not self.visited[row + 2*dRow][col + 2*dCol]):
                    self.data[row+dRow][col+dCol] = ' '
                    self.visited[row + 2*dRow][col + 2*dCol] = True
                    stack.append([row + 2*dRow, col + 2*dCol])

class MazeData3(MazeData):
    def generator(self,row,col):
        stack = [[row, col]]
        while stack:
            num = random.randint(0,len(stack)-1)
            row, col = stack.pop(random.randint(-1,0))
            for dCol, dRow in self.direction:
                if self.isInArea(row + 2*dRow, col + 2*dCol) and (
                        not self.visited[row + 2*dRow][col + 2*dCol]):
                    self.data[row+dRow][col+dCol] = ' '
                    self.visited[row + 2*dRow][col + 2*dCol] = True
                    if random.random()>0.5:
                        stack.append([row + 2*dRow, col + 2*dCol])
                    else:
                        stack.insert(0,[row + 2*dRow, col + 2*dCol])
